/*****************************************************************************
*  Copyright Statement:
*  --------------------
*  This software is protected by Copyright and the information contained
*  herein is confidential. The software may not be copied and the information
*  contained herein may not be used or disclosed except with the written
*  permission of MediaTek Inc. (C) 2005
*
*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES
*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE")
*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON
*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES,
*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF
*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT.
*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE
*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR
*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH
*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO
*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S
*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM.
*
*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE
*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE,
*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE,
*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO
*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE. 
*
*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE
*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF
*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND
*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER
*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC).
*
*****************************************************************************/
/*******************************************************************************
* Filename:
* ---------
* Event_handler.c
*
* Project:
* --------
*   MAUI
*
* Description:
* ------------
*   This file is intends for protocol/keypad/interrupt event handler .
*
* Author:
* -------
 * -------
*
*==============================================================================
*             HISTORY
* Below this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
*------------------------------------------------------------------------------
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
 *
 * removed!
 * removed!
 * removed!
*
*------------------------------------------------------------------------------
* Upper this line, this part is controlled by PVCS VM. DO NOT MODIFY!! 
*==============================================================================
*******************************************************************************/
#include "mmi_frm_prot.h"
#include "ProtocolEvents.h"
#include "CommonScreens.h"
#include "BTMMIScrGprots.h"
#include "Device.h"
#include "Mmi_msg_struct.h"
#include "mmi_frm_events_gprot.h"
#include "MMIDataType.h"
#include "kal_general_types.h"
#include "mmi_frm_events.h"
#include "stack_msgs.h"
#include "MMI_features.h"
#include "mmi_fw_trc.h"
#include "DebugInitDef_Int.h"
#include "kal_trace.h"
#include "kal_public_api.h"
#include "string.h"
#include "mmi_frm_at_util_prot.h"
#include "mmi_frm_queue_gprot.h"
#include "app_ltlcom.h"
#include "stack_config.h"
#include "wgui_categories_list.h"
#include "TimerEvents.h"
#include "mmi_frm_timer_gprot.h"
#include "stdio.h"
#include "fix_size_mem.h"
#include "mmi_cb_mgr_gprot.h"
#include "GlobalResDef.h"
#include "mmi_frm_mem_gprot.h"
#include "mmi_frm_history.h"
#include "gdi_include.h"
#include "mmi_frm_scenario_gprot.h"
#include "Mmi_frm_mem_gprot.h"
#ifdef __MET_MEX_SUPPORT__
#include "mexsystem2platform.h"
#endif

#ifdef __MMI_DSM_NEW__
#include "mrp_include.h"
#endif


/***************************************************************************** 
 * Define
 *****************************************************************************/

#define MMI_EVENT_INVALID  0
#define INTERRUPT_EVENT_GREOUP_SIZE     (4)
#define IS_INTERRUPT_EVENT_GROUP(x)    (((x)&MMI_INT_EVENT_GROUP_MASK) == MMI_INT_EVENT_GROUP_MASK)
#define MMI_FRM_PRE_INT_HDLR    1
#define MMI_FRM_POST_INT_HDLR   2
//#define __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
/***************************************************************************** 
 * Typedef 
 *****************************************************************************/
 #ifdef __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__
 typedef struct
{
    U16 groupID;
    U16 eventID[INTERRUPT_EVENT_GREOUP_SIZE];
} InterruptGroupInfo;
#endif /* __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__ */

#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
typedef struct _mmi_frm_int_mask_hdlr_struct
{
    mmi_frm_int_event_type event_mask;
    interrupt_event_hdlr int_func_ptr;
    interrupt_event_hdlr post_int_func_ptr;
} mmi_frm_int_mask_hdlr_struct;

typedef struct
{
    U16 event_id;
    mmi_frm_int_event_type int_event_macro;
} mmi_frm_int_event_convert_struct;

typedef enum
{
    MMI_FRM_INT_EVENT_SPECIFIC,
    MMI_FRM_INT_EVENT_GENERAL,
    MMI_FRM_INT_EVENT_TYPE_NUM
} mmi_frm_int_event_type_list_enum;
#endif

/* Post event mechanism */
typedef struct _mmi_post_evt_node_struct
{
    U8 flag;
    void *evt_p;
    struct _mmi_post_evt_node_struct *next;
} mmi_post_evt_node_struct;

#ifdef __MMI_LCM_PRIMITIVE_FLUSH__

#define MAX_SCREEN_LOG_SIZE (10)
#define MMI_FRM_SCREEN_ID_IVALID   (0xFFFF)    /* reserved screen ID for invalid case */

typedef struct  __mmi_frm_scr_mgm_struct
{
    MMI_BOOL    dirty;
    MMI_BOOL    changeRecording;                        /* For the controlling to filter some dummy screen such as screen adaptor */
    MMI_BOOL    sseBackupOn;                            /* For SSE module to control timing */
    MMI_BOOL    apControlBltOnce;                       /* application has used blt control API to manually flush */
    mmi_frm_scr_blt_mode_enum   bltMode;
    U16         scrnLogData[MAX_SCREEN_LOG_SIZE];       /* circular */
    S32         scrnLogIdx;
    U32         currScrnLevel;
    U32         prevScrnLevel;
}mmi_frm_scr_mgm_struct;

#endif /* __MMI_LCM_PRIMITIVE_FLUSH__ */
/*****************************************************************************
 * Global Variable                                                             
 *****************************************************************************/
PseventInfo protocolEventHandler[MAX_PROTOCOL_EVENT];
#if defined (__MMI_DUAL_SIM__) && defined (__MMI_DUAL_SIM_BACKWARD_COMPATIBILE__)
PseventInfo SlaveProtocolEventHandler[MAX_SLAVE_PROTOCOL_EVENT];
#endif

/* static event table info, e.g. table pointer, num. of table items */
const mmi_frm_event_static_info_struct g_event_table_static_info[EVENT_TABLE_END] = {
    {protocolEventHandler, sizeof(protocolEventHandler)/sizeof(PseventInfo)},
#if defined (__MMI_DUAL_SIM__) && defined (__MMI_DUAL_SIM_BACKWARD_COMPATIBILE__)
    {SlaveProtocolEventHandler, sizeof(SlaveProtocolEventHandler)/sizeof(PseventInfo)},
#endif
};

/* runtime event table info, e.g. used and max. size */
mmi_frm_event_runtime_info_struct g_event_table_runtime_info[EVENT_TABLE_END];

#ifdef __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__
U16 maxInterruptEvent;
PsInteventInfo interruptEventHandler[MAX_INTERRUPT_EVENT];
#endif /* __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__ */

#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
static BOOL g_int_evt_control_by_app = MMI_FALSE;
#endif
/* Post event link list */
static mmi_post_evt_node_struct *post_evt_header = NULL;
static U8 post_evt_num = 0;
static U8 post_evt_peak_num = 0;

#ifdef __MMI_LCM_PRIMITIVE_FLUSH__
static mmi_frm_scr_mgm_struct   mmi_frm_scr_mgm_data;
MMI_BOOL  g_mmi_frm_screen_enable_anti_blink = MMI_TRUE;  
#endif /* __MMI_LCM_PRIMITIVE_FLUSH__ */

#ifdef __VENUS_UI_ENGINE__
extern void vfx_mmi_check_update(void);
extern void vfx_mmi_update_scene(void);
extern void vfx_mmi_screen_entered(void);
#endif
extern MMI_BOOL gui_sse_get_is_dummy_screen(void);
/*****************************************************************************
 * Local Variable                                                             
 *****************************************************************************/
#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
static mmi_frm_int_mask_hdlr_struct mmi_frm_int_mask_hdlr[MMI_FRM_INT_EVENT_TYPE_NUM];
#endif

#ifdef __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__
static const InterruptGroupInfo interruptGroupEventTable[] = 
{
    {MMI_SMS_INT_EVENT_GROUP,
     {PRT_MSG_ID_MMI_SMS_DELIVER_MSG_IND,
      PRT_MSG_ID_MMI_SMS_STATUS_REPORT_IND,
      PRT_MSG_ID_MMI_SMS_MSG_WAITING_IND,
      0 /* end at 0 */
      }
     }
#if defined(__MMI_FILE_MANAGER__)
    ,{MMI_CARD_PLUG_EVENT_GROUP,
     {PRT_MMI_FMGR_CARD_PLUG_IN_IND,
      PRT_MMI_FMGR_CARD_PLUG_OUT_IND,
      0 /* end at 0 */
      }
     }
#endif /* __MMI_FILE_MANAGER__ */
};
#endif /* __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__ */


#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__

static const mmi_frm_int_event_convert_struct mmi_frm_int_event_battery_table[] = 
{
    {PMIC_CHARGER_IN,           MMI_FRM_INT_CHARGER_IN},
    {PMIC_CHARGER_OUT,          MMI_FRM_INT_CHARGER_OUT},
    {PMIC_CHARGE_COMPLETE,      MMI_FRM_INT_CHARGE_COMPLETE},
    {PMIC_USB_CHARGER_IN,       MMI_FRM_INT_USB_CHARGER_IN},
    {PMIC_USB_CHARGER_OUT,      MMI_FRM_INT_USB_CHARGER_OUT},
    {PMIC_USB_NO_CHARGER_IN,    MMI_FRM_INT_USB_NO_CHARGER_IN},
    {PMIC_USB_NO_CHARGER_OUT,   MMI_FRM_INT_USB_NO_CHARGER_OUT}
};

static const mmi_frm_int_event_convert_struct mmi_frm_int_event_convert_table[] = 
{
    {PTR_MSG_ID_SRV_SMS_WRITE_ME_SMS_IND,   MMI_FRM_INT_SMS_DELIVER},
    {MSG_ID_MMI_SMU_WRITE_SIM_RSP,          MMI_FRM_INT_SMS_DELIVER},
    {PTR_MSG_ID_SRV_SMS_DELIVER_IND,        MMI_FRM_INT_SMS_DELIVER},
    {PRT_MSG_ID_MMI_SMS_STATUS_REPORT_IND,  MMI_FRM_INT_SMS_STATUS_REPORT},
    {PRT_MSG_ID_MMI_SMS_MSG_WAITING_IND,    MMI_FRM_INT_SMS_MSG_WAITING},
    {PRT_MSG_ID_MMI_SMS_APP_DATA_IND,       MMI_FRM_INT_SMS_APP_DATA},
#if defined(__MMI_FILE_MANAGER__)
    {PRT_MMI_FMGR_CARD_PLUG_IN_IND,         MMI_FRM_INT_FMGR_CARD_PLUG_IN},
    {PRT_MMI_FMGR_CARD_PLUG_OUT_IND,        MMI_FRM_INT_FMGR_CARD_PLUG_OUT},
#endif /* __MMI_FILE_MANAGER__ */
#if defined(WAP_SUPPORT)
    {MSG_ID_WPS_PMG_NEW_MSG_IND,                MMI_FRM_INT_WAP_PMG_NEW_MSG},
    {MSG_ID_WPS_PMG_DLG_PUSH_STORAGE_FULL_IND,  MMI_FRM_INT_WAP_PMG_DLG_PUSH_STORAGE_FULL},
    {MSG_ID_WPS_PMG_REPLACE_IND,                MMI_FRM_INT_WAP_PMG_REPLACE},
    {MSG_ID_WPS_PMG_DLG_SIA_CONFIRM_REQ,        MMI_FRM_INT_WAP_PMG_DLG_SIA_CONFIRM},
    {MSG_ID_WPS_PMG_DLG_UNKNOWN_ADDR_REQ,       MMI_FRM_INT_WAP_PMG_DLG_UNKNOWN_ADDR_REQ},
#endif /* WAP_SUPPORT */
#if defined(__CCA_SUPPORT__)
    {MSG_ID_MMI_CCA_SOURCE_UI_INVALID_SETTING_IND,  MMI_FRM_INT_CCA_SOURCE_UI_INVALID_SETTING},
    {MSG_ID_MMI_CCA_SOURCE_UI_NEW_SETTING_IND,      MMI_FRM_INT_CCA_SOURCE_UI_NEW_SETTING},
#endif /* __CCA_SUPPORT__ */
	{MSG_ID_MMI_JAVA_TIMEALARM_PUSH_IND,    MMI_FRM_INT_MMI_JAVA_TIMEALARM_PUSH},
	{MSG_ID_MMI_JAVA_PUSH_INSTALL_IND,    MMI_FRM_INT_MMI_JAVA_PUSH_INSTALL},
#ifdef __CERTMAN_SUPPORT__
	{MSG_ID_MMI_CERTMAN_INVALID_CERT_IND,        MMI_FRM_INT_CERTMAN_MMI},
	{MSG_ID_MMI_CERTMAN_SELECT_USER_CERT_IND,    MMI_FRM_INT_CERTMAN_MMI},
#endif
#ifdef __MMI_USB_SUPPORT__
    {MSG_ID_MMI_EQ_USBDETECT_IND,           MMI_FRM_INT_USBDETECT},
#endif
    {MSG_ID_MMI_CC_CALL_RING_IND,           MMI_FRM_INT_MMI_CC_CALL_RING_IND},
#ifdef __SYNCML_SUPPORT__
    {MSG_ID_MMI_SYNCML_FINISH_SYNC_IND,        MMI_FRM_INT_SYNCML_FINISH_SYNC_IND},
    {MSG_ID_MMI_SYNCML_BT_ASK_ACCEPT_CONN_IND, MMI_FRM_INT_SYNCML_DEVICE_CONN_IND},
#endif
    {MSG_ID_WAP_MMA_GET_UNREAD_MSG_LIST_RSP, MMI_FRM_INT_WAP_MMA_GET_MSG},
    {MSG_ID_WAP_MMA_GET_MSG_INFO_RSP,        MMI_FRM_INT_WAP_MMA_GET_MSG},
#ifdef SYNCML_DM_SUPPORT
    {MSG_ID_DM_NOTIFICATION_INIT_SESSION_REQ_IND,   MMI_FRM_INT_DM},
    {MSG_ID_DM_GET_BOOTSTRAP_USERPIN_REQ_IND,       MMI_FRM_INT_DM},
    {MSG_ID_DM_START_DL_REQ_IND,                    MMI_FRM_INT_DM},
    {MSG_ID_DM_UPDATE_REQ_IND,                      MMI_FRM_INT_DM},
    {MSG_ID_DM_ALERT_REQ_IND,                       MMI_FRM_INT_DM},
    {MSG_ID_DM_PS_STATUS_IND,                       MMI_FRM_INT_DM},
    {MSG_ID_DM_SCOMO_INSTALL_BY_SERVER_IND,         MMI_FRM_INT_DM},
    {MSG_ID_DM_SCOMO_REMOVE_BY_SERVER_IND,          MMI_FRM_INT_DM},
#endif
#ifdef __MMI_PROV_MESSAGE_SUPPORT__
    {MSG_ID_MMI_PROVBOX_NEW_MSG_IND,    MMI_FRM_INT_PROVBOXUI_NEW_SETTING},
#endif
#ifdef __MMI_EBOOK_READER__
    {MSG_ID_MMI_EBOOK_CALLBACK_ERROR_IND, MMI_FRM_INT_EBOOK},
#endif
#ifdef __MMI_EMAIL_EMN__
    //{PRT_MMI_EMAIL_EMN_FAIL_NOTIFY_IND, MMI_FRM_INT_EMN},
#endif /* __MMI_EMAIL_EMN__ */
	/* Please add interrupt event before this one */
    {PRT_L4AUD_AUDIO_PLAY_FINISH_IND,       MMI_FRM_INT_AUDIO_PLAY_FINISH}
};

static MMI_BOOL mmi_frm_process_non_mmi_task = MMI_FALSE;


#endif

/*****************************************************************************
 * Local Function                                                              
 *****************************************************************************/
#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
/* New interrupt event internal function */
static MMI_BOOL mmi_frm_query_interrupt_event_information(mmi_frm_int_event_type frm_int_event, interrupt_event_hdlr *int_func, interrupt_event_hdlr *post_int_func);
static mmi_frm_int_event_type mmi_frm_interrupt_event_converter(U16 event_id, void *msg);

#endif

#ifdef __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__
static MMI_BOOL mmi_frm_query_interrupt_handler(U16 event_id, PsIntFuncPtr *func_ptr, PsIntFuncPtr *post_func_ptr);
#endif

static S16 mmi_frm_search_event(
            mmi_frm_event_table_enum tableType,
            U16 eventID, 
            PsFuncPtr* pFuncPtr,
            S16 startIdx, 
            MMI_BOOL doSwap,
            S16 *pNextIdx, 
            S16 *pFirstEmptyIdx, 
            MMI_BOOL *pIsMultiInTable);

static void mmi_frm_set_protocol_event_handler_int(
                mmi_frm_event_table_enum tableType, 
                U16 eventID, 
                PsFuncPtr funcPtr, 
                MMI_BOOL isMultiHandler);

static void mmi_frm_clear_protocol_event_handler_int(
                mmi_frm_event_table_enum tableType, 
                U16 eventID, 
                PsFuncPtr funcPtr);

static void mmi_frm_exec_post_event_end(void);

extern void mmi_frm_dump_screen_id(void);
#ifdef __MMI_LCM_PRIMITIVE_FLUSH__
static void mmi_frm_screen_commit(void);
extern void gdi_lcd_set_high_priority_freeze(BOOL);
extern U32 mmi_frm_get_screen_level(U16 scrn_id);
extern void gui_screen_switch_effect_reset_flag(void);
extern void gui_sse_launch(void);
#endif

#ifdef __MMI_LQT__
extern int Lup_execute_protocol_event_handler(U16 eventID, void *MsgStruct, int mod_src);
#endif
/*****************************************************************************
 * Extern data and function                                                             
 *****************************************************************************/

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_execute_current_protocol_handler
 * DESCRIPTION
 *  This function is used for executes current protocol func handler.
 * PARAMETERS
 *  eventID         [IN]  Unique Protocol/System EventID       
 *  MsgStruct       [IN]  The pointer to the Local parameter.      
 *  mod_src         [IN]  Source module ID.     
 *  Message         [IN]  The pointer to the ILM.       
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_execute_current_protocol_handler(U16 eventID, void *MsgStruct, int mod_src, void *Message)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    S16 idx = 0;
    MMI_BOOL isMultiHandler = MMI_FALSE, isExecuted;
    S16 nextIdxToSearch = 0;    /* used for multi-handler to enhance search efficiency */
    PsExtPeerIntFuncPtr currFuncPtr = NULL;
    mmi_frm_event_table_enum tableType = EVENT_TABLE_MASTER;

#ifdef __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__
    PsIntFuncPtr IntFunc = NULL, PostIntFunc = NULL;
    PsExtPeerIntFuncPtr currInterruptFuncPtr = NULL, currPostInterruptFuncPtr = NULL;
    U8 interrup_result = MMI_FALSE; /* False not handle interrupt, True will handle */
#endif /* __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__ */

#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
    /* new interrupt event mechanism */
    MMI_BOOL query_result = MMI_FALSE, execute_result = MMI_FALSE;
    interrupt_event_hdlr int_func = NULL, post_int_func = NULL;
    mmi_frm_int_event_type current_frm_int_event;
#endif
        
#if defined (MMI_EVENT_PROFILING)
    kal_uint32 start_tick, end_tick;
    static kal_uint32 accu_ticks = 0;
    static U32 accu_count = 0;
#endif /* defined (MMI_EVENT_PROFILING) */ 
    mmi_frm_pre_post_protocol_event_struct event;
    mmi_ret ret;
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/

#if defined(__MMI_DSM_NEW__)  &&  defined(__MMI_DSM_NETWORK_HOOK__)//huangsunbo 20120216
{
	MMI_BOOL unet_Soc_Event_Handler(U16 eventID, void* MsgStruct);
	if (unet_Soc_Event_Handler(eventID, MsgStruct))
		return;
}
#endif


#if defined (MMI_EVENT_PROFILING)
    kal_get_time(&start_tick);
#endif 

#if defined (__MMI_DUAL_SIM__) && defined (__MMI_DUAL_SIM_BACKWARD_COMPATIBILE__)
    if (mod_src == MOD_L4C_2)
    {
        tableType = EVENT_TABLE_SLAVE;  /* use slave event table */
    }
#endif /* __MMI_DUAL_SIM__ && __MMI_DUAL_SIM_BACKWARD_COMPATIBILE__ */
        
    /* Search events in protocol event handler table */
    idx = mmi_frm_search_event(
            tableType,
            eventID, 
            (PsFuncPtr*) &currFuncPtr,
            0, 
            MMI_TRUE, 
            &nextIdxToSearch, 
            NULL, 
            &isMultiHandler);


#if defined (MMI_EVENT_PROFILING)
    if (idx > 0)
        accu_count += idx;
#endif /* defined (MMI_EVENT_PROFILING) */ 

#ifdef __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__
    /* Old Search events in interrupt event handler table */
    mmi_frm_query_interrupt_handler(eventID, &IntFunc, &PostIntFunc);
    currInterruptFuncPtr = (PsExtPeerIntFuncPtr) IntFunc;
    currPostInterruptFuncPtr = (PsExtPeerIntFuncPtr) PostIntFunc;
    /* Old interruption mechanism */
    if (currInterruptFuncPtr)
    {
        interrup_result = (*currInterruptFuncPtr) (MsgStruct, mod_src, Message) ? MMI_TRUE : MMI_FALSE;
    }
#endif /* __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__ */

#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
    /* New Search events in interrupt event handler mask table */
    current_frm_int_event = mmi_frm_interrupt_event_converter(eventID, MsgStruct);
#if defined(__SF_API_EX__)
{	
extern int SFOS32_Mtk_InterruptEventHandlerBlocked(U64 uEvent);
	if (SFOS32_Mtk_InterruptEventHandlerBlocked(current_frm_int_event) !=0)
	{
		return;
	}
}
#endif
    if (current_frm_int_event > 0)
    {
        query_result = mmi_frm_query_interrupt_event_information(current_frm_int_event, &int_func, &post_int_func);
    }
    if (query_result && int_func)
    {
        /* New interruption mechanism */
        execute_result = (*int_func)(current_frm_int_event);
    }
#endif
    MMI_FRM_INIT_EVENT(&event, EVT_ID_PRE_PROTOCOL);
    event.message = Message;
    ret = MMI_FRM_CB_EMIT_EVENT(&event);

    if ((currFuncPtr)  
#ifdef __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__
        && (!interrup_result) 
#endif /* __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__ */

#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
        && (!execute_result)
#endif
     && (ret != MMI_RET_STOP_PROTOCOL))
     {

        do {
            MMI_TRACE(MMI_FW_TRC_G1_FRM, MMI_FRM_INFO_EVENT_EXECURPTO_HDLR, tableType, eventID, currFuncPtr, isMultiHandler);

            isExecuted = (*currFuncPtr) (MsgStruct, mod_src, Message) ? MMI_TRUE: MMI_FALSE;

            currFuncPtr = NULL; /* reset handler to NULL */

            /* search and execute next handler if (1) multi-handler and (2) event is not executed */
            if (isMultiHandler && !isExecuted)
            {
                idx = mmi_frm_search_event(
                        tableType,
                        eventID, 
                        (PsFuncPtr*) &currFuncPtr,
                        nextIdxToSearch, 
                        MMI_TRUE, 
                        &nextIdxToSearch, 
                        NULL, 
                        NULL);

                if (idx < 0)
                {
                    MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, MMI_FRM_INFO_EVENT_EXECURPTO_NO_HDLR, tableType, eventID, currFuncPtr);
                    
                }
            }
        } while (currFuncPtr);
    }
    else
    {
        MMI_TRACE(MMI_FW_TRC_G1_FRM, MMI_FRM_INFO_EVENT_EXECURPTO_NO_HDLR, tableType, eventID, currFuncPtr);
    }
    
#ifdef __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__
    if (currPostInterruptFuncPtr)
    {
        (*currPostInterruptFuncPtr) (MsgStruct, mod_src, Message);
    }
#endif /* __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__ */

#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
    /* New interruption mechanism */    
    if (query_result && post_int_func)
    {
        execute_result = (*post_int_func)(current_frm_int_event) ? MMI_TRUE : MMI_FALSE;
    }
#endif

#if defined (MMI_EVENT_PROFILING)
    kal_get_time(&end_tick);
    accu_ticks += (end_tick - start_tick);
    MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, MMI_EVENT_TRC_EVENT_PROFILING_COUNT, accu_count);
    MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, MMI_EVENT_TRC_EVENT_PROFILING_TICKS, accu_ticks);
    MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, MMI_EVENT_TRC_EVENT_PROFILING_MAX, g_event_table_runtime_info[tableType].max_events);
#endif /* defined (MMI_EVENT_PROFILING) */ 
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_set_protocol_event_handler
 * DESCRIPTION
 *  This function is used for register the protocol event handler. Whenever 
 *  an event is received from the protocol or system corresponding function 
 *  is executed.
 * PARAMETERS
 *  eventID         [IN] Unique Protocol/System EventID.       
 *  funcPtr         [IN] Function to be executed whenever a event is received from the protocol or system
 *  isMultiHandler  [IN] is multi-handler or not. for multi-handler, it shall return MMI_TRUE when event is handled (taken) by it.
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_set_protocol_event_handler(U16 eventID, PsIntFuncPtr funcPtr, MMI_BOOL isMultiHandler)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
#ifdef __I51__
    if( eventID == MSG_ID_APP_SOC_GET_HOST_BY_NAME_IND || eventID == MSG_ID_APP_SOC_NOTIFY_IND )
    {
        isMultiHandler = MMI_TRUE;
    }else if( eventID == MSG_ID_MMI_PS_GET_GPRS_DATA_COUNTER_RSP )
    {
        isMultiHandler = MMI_FALSE;
}
#endif

#ifdef __MMI_JAVA_STORE__ 
    if( eventID == MSG_ID_APP_SOC_GET_HOST_BY_NAME_IND || eventID == MSG_ID_APP_SOC_NOTIFY_IND )
    {
        isMultiHandler = MMI_TRUE;
    }else if( eventID == MSG_ID_MMI_PS_GET_GPRS_DATA_COUNTER_RSP )
    {
        isMultiHandler = MMI_FALSE;
}
#endif
    mmi_frm_set_protocol_event_handler_int(EVENT_TABLE_MASTER, eventID, (PsFuncPtr)funcPtr, isMultiHandler);
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_clear_protocol_event_handler
 * DESCRIPTION
 *  This is used to clear protocol event handler
 * PARAMETERS
 *  eventID     [IN] event ID to clear
 *  funcPtr     [IN] handler of event ID to clear for multi-handler. can just assign NULL for single-handler event.
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_clear_protocol_event_handler(U16 eventID, PsIntFuncPtr funcPtr)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
#ifdef __I51__
    if( eventID == MSG_ID_APP_SOC_GET_HOST_BY_NAME_IND || eventID == MSG_ID_APP_SOC_NOTIFY_IND ){
        if( funcPtr == NULL ){
            extern void i51AdeSafeClearNetHandler(U16 EventID);
            i51AdeSafeClearNetHandler(eventID);
            return;
        }
    }else if( eventID == MSG_ID_MMI_PS_GET_GPRS_DATA_COUNTER_RSP ){
        if( funcPtr  )  funcPtr = NULL;
    }
#endif

#ifdef __MMI_JAVA_STORE__ 
    if( eventID == MSG_ID_APP_SOC_GET_HOST_BY_NAME_IND || eventID == MSG_ID_APP_SOC_NOTIFY_IND )
    {
if( funcPtr == NULL )  return;
    }else if( eventID == MSG_ID_MMI_PS_GET_GPRS_DATA_COUNTER_RSP )
    {
        if( funcPtr  )  funcPtr = NULL;
}
#endif
    mmi_frm_clear_protocol_event_handler_int(EVENT_TABLE_MASTER, eventID, (PsFuncPtr)funcPtr);
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_get_protocol_event_handler
 * DESCRIPTION
 *  This is used to get protocal event handler(only support MSG_ID_MMI_EQ_KEYPAD_DETECT_IND)
 * PARAMETERS
 *  eventID     :[IN] event ID
 *  funcPtr     :[IN] protocol event handler of eventID
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_get_protocol_event_handler(U16 eventID, PsFuncPtr* pFuncPtr)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    PsFuncPtr funcPtr = NULL;
    S16 idx = -1, firstNotUsed = -1;
    MMI_BOOL isMultiInTable;
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    MMI_ASSERT(eventID == MSG_ID_MMI_EQ_KEYPAD_DETECT_IND);

    idx = mmi_frm_search_event(
            EVENT_TABLE_MASTER,
            eventID, 
            &funcPtr,
            0, 
            MMI_FALSE, 
            NULL, 
            &firstNotUsed, 
            &isMultiInTable);
    if (idx >= 0)
    {
       *pFuncPtr = funcPtr;
    }
    else
    {
       *pFuncPtr = NULL;
    }
}

#ifdef __MET_MEX_SUPPORT__
/*****************************************************************************
 * FUNCTION
 *  mex_mmi_frm_get_protocol_event_handler
 * DESCRIPTION
 *  This is used to get protocal event handler(only support MSG_ID_MMI_EQ_KEYPAD_DETECT_IND)
 * PARAMETERS
 *  eventID     :[IN] event ID
 *  funcPtr     :[IN] protocol event handler of eventID
 * RETURNS
 *  void
 *****************************************************************************/
void mex_mmi_frm_get_protocol_event_handler(U16 eventID, PsFuncPtr* pFuncPtr)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    PsFuncPtr funcPtr = NULL;
    S16 idx = -1, firstNotUsed = -1;
    MMI_BOOL isMultiInTable;
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/

    idx = mmi_frm_search_event(
            EVENT_TABLE_MASTER,
            eventID, 
            &funcPtr,
            0, 
            MMI_FALSE, 
            NULL, 
            &firstNotUsed, 
            &isMultiInTable);
    if (idx >= 0)
    {
       *pFuncPtr = funcPtr;
    }
    else
    {
       *pFuncPtr = NULL;
    }
}

#endif

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_search_event
 * DESCRIPTION
 *  search event in eventTable.
 * PARAMETERS
 *  tableType       [IN]  type of event table to search
 *  eventID         [IN]  event ID to search
 *  pFuncPtr        [IN/OUT] [IN] handler to search, or NULL to search event ID only [OUT] handler found for given event ID
 *  startIdx        [IN]  start index
 *  doSwap          [IN]  swap found event or not (now only swap when executing event)
 *  pNextIdx        [OUT] next index to search
 *  pFirstEmptyIdx  [OUT] index of 1st empty
 *  pIsMultiInTable [OUT] is multi-handler found in event table
 * RETURNS
 *  index found or -1 (not found)
 *****************************************************************************/
static S16 mmi_frm_search_event(
            mmi_frm_event_table_enum tableType,
            U16 eventID, 
            PsFuncPtr* pFuncPtr,
            S16 startIdx, 
            MMI_BOOL doSwap,
            S16 *pNextIdx, 
            S16 *pFirstEmptyIdx, 
            MMI_BOOL *pIsMultiInTable)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    S16 idx = -1;
    S16 maxEvents = g_event_table_runtime_info[tableType].max_events;
    PseventInfo *eventTable = g_event_table_static_info[tableType].table;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    if (pFirstEmptyIdx)
        *pFirstEmptyIdx = -1;

    /* Search events in protocol event handler table */
    for (idx = startIdx; idx < maxEvents; idx++)
    {
        /* eventID match */
        if (eventTable[idx].eventID == eventID)
        {
            /* if handler type is diff., return type in table */
            if ((pIsMultiInTable) && (*pIsMultiInTable != (MMI_BOOL)eventTable[idx].flagMulti))
                *pIsMultiInTable = (MMI_BOOL)eventTable[idx].flagMulti;

            /* search for handler or not */
            if (pFuncPtr)
    {
                /* match eventID only, no handler to search */
                if (*pFuncPtr == NULL)
                {
                    *pFuncPtr = eventTable[idx].entryFuncPtr;
                }
                /* has handler to search */
                else
                {
                    /* handler not found */
                    if (*pFuncPtr != eventTable[idx].entryFuncPtr)
        {
                        continue;   /* keep searching */
                    }
                    /* else: handler found */
                }
            }

            if (pNextIdx) /* next index to search */
                *pNextIdx = idx+1;

            if (doSwap && (idx > 0))
            {   /* improve the search efficiently */
                PseventInfo tmpEvent = eventTable[idx];
                eventTable[idx]     = eventTable[idx-1];
                eventTable[idx-1]   = tmpEvent;
                idx--;
            }
         
            break;
        }
        
        /* find 1st empty at the same time */
        if (pFirstEmptyIdx && (*pFirstEmptyIdx == -1) && (eventTable[idx].eventID == MMI_EVENT_INVALID))
        {
            *pFirstEmptyIdx = idx;
        }

    }

    if (idx < maxEvents)
        return idx;
    else
        return -1;  /* not found */
}

#ifdef __MEDIA_TECH_SUPPORT__
#include "mt_def.h"
#if (MT_PLATFORM_VER>=0x09120)
MMI_BOOL mt_mmi_frm_search_event(U16 eventID, MMI_BOOL isMultiHandler)
{
	S16  firstNotUsed = -1;
         PsFuncPtr funcToSearch = NULL;
	  MMI_BOOL isMultiInTable = isMultiHandler;


	 mmi_frm_search_event(
           EVENT_TABLE_MASTER,
            eventID,
            &funcToSearch,
            0,
            MMI_FALSE,
            NULL,
            &firstNotUsed,
            &isMultiInTable);

	 return isMultiInTable;

}
#endif/*MT_PLATFORM_VER>=0x09120*/
#endif/*__MEDIA_TECH_SUPPORT__*/
/*****************************************************************************
 * FUNCTION
 *  mmi_frm_set_protocol_event_handler_int
 * DESCRIPTION
 *  This function is used for register the protocol event handler. Whenever 
 *  an event is received from the protocol or system corresponding function 
 *  is executed.
 * PARAMETERS
 *  tableType       [IN] event table type
 *  eventID         [IN] Unique Protocol/System EventID.       
 *  funcPtr         [IN] Function to be executed whenever a event is received from the protocol or system
 *  isMultiHandler  [IN] is multi-handler or not. for multi-handler, it shall return MMI_TRUE when event is handled (taken) by it.
 * RETURNS
 *  void
 *****************************************************************************/
static void mmi_frm_set_protocol_event_handler_int(mmi_frm_event_table_enum tableType, U16 eventID, PsFuncPtr funcPtr, MMI_BOOL isMultiHandler)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    static U16 maxUsedInHistory[EVENT_TABLE_END] = {0};
    S16 idx = -1, firstNotUsed = -1;
    MMI_BOOL isMultiInTable = isMultiHandler;  /* initial to same as input */
    PsFuncPtr funcToSearch = NULL;
    PseventInfo *eventTable = g_event_table_static_info[tableType].table;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    MMI_ASSERT(eventID != 0);
    MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, TRC_MMI_FRM_EVENT_SETPTO_HDLR,
              eventID, funcPtr, isMultiHandler);
    MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, TRC_MMI_FRM_EVENT_SETPTO_HDLR_DETAIL,
              tableType, g_event_table_runtime_info[tableType].used_events, g_event_table_runtime_info[tableType].max_events);

    /* serach */
    if (isMultiHandler)
    {
        funcToSearch = funcPtr;
        MMI_ASSERT(funcPtr != NULL);    /* funcPtr=NULL is only for single-handler */
   }

    idx = mmi_frm_search_event(
            tableType,
            eventID, 
            &funcToSearch,
            0, 
            MMI_FALSE, 
            NULL, 
            &firstNotUsed, 
            &isMultiInTable);
#ifdef __MEDIA_TECH_SUPPORT__
    {
        extern BOOL mt_ScrnInIdle(void);
        if(mt_ScrnInIdle()==FALSE && isMultiHandler!=isMultiInTable)
            return;
    }
#endif

    MMI_ASSERT(isMultiHandler == isMultiInTable);  /* handler type mismatch with existing in table */

    /* found */
    if (idx >= 0)
    {
        /* single-handler */
        if (!isMultiHandler)
        {
            if (funcPtr != NULL)
            {
                /* just need to update */
                eventTable[idx].entryFuncPtr = funcPtr;
            }
            else
            {
                /* funcPtr=NULL, means clear => reset it */
                memset(&eventTable[idx], 0, sizeof(PseventInfo));
                g_event_table_runtime_info[tableType].used_events--;
            }
        }
        /* multi-handler: eventID/funcPtr already exists, do nothing */
    }
    /* not found */
    else
    {
        if (funcPtr != NULL)
        {
            /* newly set */
            if (firstNotUsed != -1)
            {
                idx = firstNotUsed;
            }
            else
            {
                /* need to enlarge current searching list */
                idx = g_event_table_runtime_info[tableType].max_events;
                g_event_table_runtime_info[tableType].max_events++;
                MMI_ASSERT(g_event_table_runtime_info[tableType].max_events < g_event_table_static_info[tableType].num_of_events);
            }
            g_event_table_runtime_info[tableType].used_events++;
            eventTable[idx].eventID       = eventID;
            eventTable[idx].entryFuncPtr  = funcPtr;
            eventTable[idx].flagMulti     = (U8)isMultiHandler;
        }
        else
        {
            /* funcPtr=NULL, means clear. but not found => do nothing */
        }
    }

    /* recycle not-used items in the tail of list. It is for searching efficency */
    for (idx = (g_event_table_runtime_info[tableType].max_events - 1); idx >= 0; idx--)
    {
        if (eventTable[idx].eventID != MMI_EVENT_INVALID)
        {
            break;
        }
    }
    g_event_table_runtime_info[tableType].max_events= idx + 1;

    /* record the max value for array size analysis */
    if (maxUsedInHistory[tableType] < g_event_table_runtime_info[tableType].max_events)
    {
        MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, MMI_EVENT_TRC_SET_PROTOCOL_EVENT_HDLR_MAX_1, maxUsedInHistory[tableType]);
        maxUsedInHistory[tableType] = g_event_table_runtime_info[tableType].max_events;
        MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, MMI_EVENT_TRC_SET_PROTOCOL_EVENT_HDLR_MAX_2, maxUsedInHistory[tableType]);
    }
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_clear_protocol_event_handler_int
 * DESCRIPTION
 *  This is used to clear protocol event handler
 * PARAMETERS
 *  tableType   [IN] event table type
 *  eventID     [IN] event ID to clear
 *  funcPtr     [IN] handler of event ID to clear for multi-handler. can just assign NULL for single-handler event.
 * RETURNS
 *  void
 *****************************************************************************/
static void mmi_frm_clear_protocol_event_handler_int(mmi_frm_event_table_enum tableType, U16 eventID, PsFuncPtr funcPtr)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    S16 idx = -1;
    MMI_BOOL isMultiInTable = MMI_FALSE;
    PsFuncPtr funcToClear = funcPtr;
    PseventInfo *eventTable = g_event_table_static_info[tableType].table;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    idx = mmi_frm_search_event(
            tableType,
            eventID, 
            &funcToClear,
            0, 
            MMI_FALSE, 
            NULL, 
            NULL, 
            &isMultiInTable);
    #ifdef __MEDIA_TECH_SUPPORT__
            {
                extern BOOL mt_ScrnInIdle(void);
                if(mt_ScrnInIdle()==FALSE && idx>=0 && isMultiInTable && !funcPtr)
                return;
            }
    #endif 

    if (idx >= 0)  /* found */
    {
        if (isMultiInTable)
        {
            MMI_ASSERT(funcPtr);    /* can't use NULL for multi-handler */
        }

        /* shows actual (eventID, funcPtr) to clear */
        MMI_TRACE(MMI_FW_TRC_G1_FRM, TRC_MMI_FRM_EVENT_CLRPTO_HDLR, tableType, eventID, funcToClear);

        memset(&eventTable[idx], 0, sizeof(PseventInfo));
        g_event_table_runtime_info[tableType].used_events--;

        /* recycle not-used items in the tail of list. It is for searching efficency */
        for (idx = (g_event_table_runtime_info[tableType].max_events - 1); idx >= 0; idx--)
        {
            if (eventTable[idx].eventID != MMI_EVENT_INVALID)
            {
                break;
            }
        }
        g_event_table_runtime_info[tableType].max_events= idx + 1;
    }
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_clear_all_protocol_event_handler
 * DESCRIPTION
 *  This is used to clear all the protocol event handlers
 * PARAMETERS
 *  void
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_clear_all_protocol_event_handler(void)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    MMI_TRACE(MMI_FW_TRC_G1_FRM, TRC_MMI_FRM_EVENT_CLRALLPTO_HDLR, EVENT_TABLE_MASTER);

    memset(protocolEventHandler, 0, sizeof(PseventInfo)*g_event_table_runtime_info[EVENT_TABLE_MASTER].max_events); 
    memset(&g_event_table_runtime_info[EVENT_TABLE_MASTER], 0, sizeof(mmi_frm_event_runtime_info_struct));
    
    mmi_frm_set_protocol_event_handler(MSG_ID_TST_INJECT_STRING, (PsIntFuncPtr)mmi_proc_inject_string, MMI_TRUE);

#if defined (__MMI_DUAL_SIM__) && defined (__MMI_DUAL_SIM_BACKWARD_COMPATIBILE__)
    mmi_frm_clear_all_slave_protocol_event_handler();
#endif
}


#if defined (__MMI_DUAL_SIM__) && defined (__MMI_DUAL_SIM_BACKWARD_COMPATIBILE__)
/*****************************************************************************
 * FUNCTION
 *  mmi_frm_set_slave_protocol_event_handler
 * DESCRIPTION
 *  This function is used for register the protocol event handler for slave card. 
 *  Whenever an event is received from the protocol or system corresponding function 
 *  is executed.
 * PARAMETERS
 *  eventID     [IN] Unique Protocol/System EventID.       
 *  funcPtr         [IN] Function to be executed whenever a event is received from the protocol or system
 *  isMultiHandler  [IN] is multi-handler or not
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_set_slave_protocol_event_handler(U16 eventID, PsIntFuncPtr funcPtr, MMI_BOOL isMultiHandler)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
#ifdef __MMI_JAVA_STORE__ 
    if( eventID == MSG_ID_APP_SOC_GET_HOST_BY_NAME_IND || eventID == MSG_ID_APP_SOC_NOTIFY_IND )
    {
        isMultiHandler = MMI_TRUE;
    }else if( eventID == MSG_ID_MMI_PS_GET_GPRS_DATA_COUNTER_RSP )
    {
        isMultiHandler = MMI_FALSE;
}
#endif
    mmi_frm_set_protocol_event_handler_int(EVENT_TABLE_SLAVE, eventID, (PsFuncPtr)funcPtr, isMultiHandler);
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_clear_slave_protocol_event_handler
 * DESCRIPTION
 *  This is used to clear protocol event handler
 * PARAMETERS
 *  eventID     [IN] Clear the handler of event ID.       
 *  funcPtr     [IN] handler of event ID to clear for multi-handler. can just assign NULL for single-handler event.
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_clear_slave_protocol_event_handler(U16 eventID, PsIntFuncPtr funcPtr)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
#ifdef __MMI_JAVA_STORE__ 
    if( eventID == MSG_ID_APP_SOC_GET_HOST_BY_NAME_IND || eventID == MSG_ID_APP_SOC_NOTIFY_IND )
    {
if( funcPtr == NULL )  return;
    }else if( eventID == MSG_ID_MMI_PS_GET_GPRS_DATA_COUNTER_RSP )
    {
        if( funcPtr  )  funcPtr = NULL;
}
#endif
    mmi_frm_clear_protocol_event_handler_int(EVENT_TABLE_SLAVE, eventID, (PsFuncPtr)funcPtr);
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_clear_all_slave_protocol_event_handler
 * DESCRIPTION
 *  This is used to clear all the protocol event handlers
 * PARAMETERS
 *  void
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_clear_all_slave_protocol_event_handler(void)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    memset(SlaveProtocolEventHandler, 0, sizeof(PseventInfo) * g_event_table_runtime_info[EVENT_TABLE_SLAVE].max_events); 
    memset(&g_event_table_runtime_info[EVENT_TABLE_SLAVE], 0, sizeof(mmi_frm_event_runtime_info_struct));
    
    mmi_frm_set_slave_protocol_event_handler(MSG_ID_TST_INJECT_STRING, (PsIntFuncPtr)mmi_proc_inject_string, MMI_TRUE);
}
#endif /* __MMI_DUAL_SIM__ && __MMI_DUAL_SIM_BACKWARD_COMPATIBILE__ */


#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
/*****************************************************************************
 * FUNCTION
 *  mmi_frm_query_interrupt_event_information
 * DESCRIPTION
 *  This function could query interrupt event information.
 * PARAMETERS
 *  eventID      [IN]        interrupt event id
 *  int_func     [OUT]       interrupt event pre handler
 *  post_int_func[OUT]       interrupt event post handler   
 * RETURNS
 *  Return MMI_TURE if find the information slot, otherwise, return MMI_FLASE
 *****************************************************************************/
static MMI_BOOL mmi_frm_query_interrupt_event_information(mmi_frm_int_event_type frm_int_event, interrupt_event_hdlr *int_func, interrupt_event_hdlr *post_int_func)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    int count;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    /* We set specific interrupt event as higher priority than general ones */
    for (count = MMI_FRM_INT_EVENT_SPECIFIC; count < MMI_FRM_INT_EVENT_TYPE_NUM; count++)
    {
        if (frm_int_event & mmi_frm_int_mask_hdlr[count].event_mask)
        {
            if (int_func)
            {
                *int_func = mmi_frm_int_mask_hdlr[count].int_func_ptr;
            }
            if (post_int_func)
            {
                *post_int_func = mmi_frm_int_mask_hdlr[count].post_int_func_ptr;
            }
            return MMI_TRUE;
        }
    }
    
    return MMI_FALSE;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_get_frm_int_event_macro
 * DESCRIPTION
 *  This function will get framework interrupt event macro from convert table
 * PARAMETERS
 *  event_id       [IN]       interrupt event id
 *  msg            [IN]       primitive's local parameter
 * RETURNS
 *  Reture framework interrupt event macro
 *****************************************************************************/
static mmi_frm_int_event_type mmi_frm_get_frm_int_event_macro(U16 int_event, const mmi_frm_int_event_convert_struct *int_event_convert_table, U8 table_size)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    U8  count;
    mmi_frm_int_event_type frm_int_event_macro = 0;
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    for (count = 0; count < table_size; count++)
    {
        if (int_event_convert_table[count].event_id == int_event)
        {
            frm_int_event_macro = int_event_convert_table[count].int_event_macro;
            break;
        }
    }
    return frm_int_event_macro;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_interrupt_event_converter
 * DESCRIPTION
 *  This function will convert protocol interrupt event to framework interrupt
 *  event macro.
 * PARAMETERS
 *  event_id       [IN]       interrupt event id
 *  msg            [IN]       primitive's local parameter
 * RETURNS
 *  Reture framework interrupt event macro
 *****************************************************************************/
static mmi_frm_int_event_type mmi_frm_interrupt_event_converter(U16 event_id, void *msg)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    mmi_frm_int_event_type frm_interrupt_event = 0;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    switch (event_id)
    {
        case PRT_EQ_GPIO_DETECT_IND:
        {
            mmi_eq_gpio_detect_ind_struct *gpio_detect_ind = (mmi_eq_gpio_detect_ind_struct *)msg;
            switch (gpio_detect_ind->gpio_device)
            {
                case EXT_DEV_CLAM_CLOSE:
                {
                    frm_interrupt_event = MMI_FRM_INT_CLAM_CLOSE;
                    break;
                }
                case EXT_DEV_CLAM_OPEN:
                {
                    frm_interrupt_event = MMI_FRM_INT_CLAM_OPEN;
                    break;
                }
                case EXT_DEV_EARPHONE:
                {
                    if (gpio_detect_ind->on_off == 1)
                    {
                        frm_interrupt_event = MMI_FRM_INT_EARPHONE_PLUG_IN;
                    }
                    else
                    {
                        frm_interrupt_event = MMI_FRM_INT_EARPHONE_PLUG_OUT;
                    }
                    break;
                }
            }
            break;
        }
        case PRT_BATTERY_STATUS_IND:
        {
            mmi_eq_battery_status_ind_struct *battery_status_ind = (mmi_eq_battery_status_ind_struct*)msg;

            frm_interrupt_event = mmi_frm_get_frm_int_event_macro(
                                      battery_status_ind->battery_status,
                                      mmi_frm_int_event_battery_table,
                                      sizeof(mmi_frm_int_event_battery_table) / sizeof(mmi_frm_int_event_battery_table[0]));
            /* For low battery indication */
            if (battery_status_ind->battery_status == PMIC_VBAT_STATUS)
            {
                if (battery_status_ind->battery_voltage == BATTERY_LOW_WARNING)
                {
                    frm_interrupt_event = MMI_FRM_INT_BATTERY_LOW_WARNING;
                }
                else if (battery_status_ind->battery_voltage == BATTERY_LOW_TX_PROHIBIT)
                {
                    frm_interrupt_event = MMI_FRM_INT_BATTERY_LOW_TX_PROHIBIT;
                }
            }
            break;
        }
        case MSG_ID_TIMER_EXPIRY:
        case MSG_ID_MMI_EQ_POWER_ON_IND:
        case MSG_ID_MMI_EQ_KEYPAD_DETECT_IND:
        {
            break;
        }
        default:
        {
            frm_interrupt_event = mmi_frm_get_frm_int_event_macro(
                                      event_id, 
                                      mmi_frm_int_event_convert_table,
                                      sizeof(mmi_frm_int_event_convert_table) / sizeof(mmi_frm_int_event_convert_table[0]));
            break;
        }
    }
    return frm_interrupt_event;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_process_non_mmi_task_interrupt
 * DESCRIPTION
 *  This function is an internal one which will set interrupt event handler
 *  into interrupt information table.
 * PARAMETERS
 *  mmi_frm_int_event_type       [IN]       interrupt event
 *  is_set                       [IN]       set non-mmi task popup screen 
 * RETURNS
 *  void
 *****************************************************************************/
static void mmi_frm_process_non_mmi_task_interrupt(mmi_frm_int_event_type interrupt_event, MMI_BOOL is_set)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    MMI_BOOL mmi_arg = MMI_FALSE;
    kal_bool kal_arg = KAL_FALSE;
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    if (is_set)
    {
        mmi_arg = MMI_TRUE;
        kal_arg = KAL_TRUE;
    }

    #ifdef OBIGO_Q03C
        if (interrupt_event & MMI_FRM_INT_WAP_MMS)
        {
            wap_suppress_popup(kal_arg);
        }        
    #endif /* OBIGO_Q03C */
    #if defined(__MMI_BT_MTK_SUPPORT__)
        if (interrupt_event & MMI_FRM_INT_BT_TASK)
        {
            mmi_bt_suppress_popup(mmi_arg, (U32)(interrupt_event & MMI_FRM_INT_BT_TASK));
        }
    #endif /* defined(__MMI_BT_MTK_SUPPORT__) */
    mmi_frm_process_non_mmi_task = is_set;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_block_interrupt_event_int
 * DESCRIPTION
 *  This function is an internal one which will set interrupt event handler
 *  into interrupt information table.
 * PARAMETERS
 *  int_event_p           [IN]       pre interrupt event handler
 *  post_int_event_p      [IN]       post interrupt event handler
 *  interrupt_event       [IN]       framework interrupt event macro
 *  event_type            [IN]       to decide general or specific event  
 * RETURNS
 *  void
 *****************************************************************************/
static void mmi_frm_block_interrupt_event_int(mmi_frm_int_event_type interrupt_event, interrupt_event_hdlr int_event_p, interrupt_event_hdlr post_int_event_p, U8 event_type)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    /* 
     * Non-MMI task interruption is not through the protocol event process, so it needs to set flag to 
     * stop popup screen after EntryNewScreen and reset it when exit the screen
     */
    if (interrupt_event & MMI_FRM_INT_NON_MMI_TASK_EVENTS)
    {
        if (int_event_p)
        {
            mmi_frm_process_non_mmi_task_interrupt(interrupt_event, MMI_TRUE);
        }
        else if (!int_event_p && mmi_frm_process_non_mmi_task)  /* if int_event_p is NULL which means user want to clear this handler */
        {
            mmi_frm_process_non_mmi_task_interrupt(interrupt_event, MMI_FALSE);
        }
    }

    /* This action will only register the events and handlers in the last time calling this interface */
    mmi_frm_int_mask_hdlr[event_type].event_mask = interrupt_event;
    mmi_frm_int_mask_hdlr[event_type].int_func_ptr = int_event_p;
    mmi_frm_int_mask_hdlr[event_type].post_int_func_ptr = post_int_event_p;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_pre_block_interrupt_event_handler
 * DESCRIPTION
 *  This function is an internal one which will block popup screen caused by
 *  interrupt event handler.
 * PARAMETERS
 *  interrupt_event       [IN]       framework interrupt event macro  
 * RETURNS
 *  Return MMI_FALSE to let protocol handler be executed, otherwise, 
 *  return MMI_TRUE.
 *****************************************************************************/
static U8 mmi_frm_pre_block_interrupt_event_handler(mmi_frm_int_event_type interrupt_event)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
	
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    SetInterruptPopupDisplay(POPUP_ALL_OFF);

    return MMI_FALSE;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_post_block_interrupt_event_handler
 * DESCRIPTION
 *  This function is an internal one which will reset the flag of popup screen.
 * PARAMETERS
 *  interrupt_event       [IN]       framework interrupt event macro  
 * RETURNS
 *  Return MMI_FALSE always (remain for expansion).
 *****************************************************************************/
static U8 mmi_frm_post_block_interrupt_event_handler(mmi_frm_int_event_type interrupt_event)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
	
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/    
    SetInterruptPopupDisplay(POPUP_ALL_ON);

    return MMI_FALSE;
}
#endif


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_block_interrupt_event_handler
 * DESCRIPTION
 *  This function will set event handler which could process what application want 
 *  when the interrupt event is blocked by mmi task.
 * PARAMETERS
 *  interrupt_event       [IN]       framework interrupt event macro
 *  int_event_p           [IN]       pre interrupt event handler
 *  post_int_event_p      [IN]       post interrupt event handler
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_block_interrupt_event_handler(mmi_frm_int_event_type interrupt_event, interrupt_event_hdlr int_event_p, interrupt_event_hdlr post_int_event_p)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
    MMI_TRACE(MMI_FW_TRC_G1_FRM, TRC_MMI_FRM_EVENT_BLOCK_INT_HDLR, interrupt_event);
    mmi_frm_block_interrupt_event_int(
        interrupt_event, 
        int_event_p,
        post_int_event_p,
        MMI_FRM_INT_EVENT_SPECIFIC);
#endif
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_block_general_interrupt_event
 * DESCRIPTION
 *  This function could block all the interruptive popup screen when the general
 *  interrupt event is blocked by mmi task.
 * PARAMETERS
 *  interrupt_event       [IN]       framework interrupt event macro
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_block_general_interrupt_event(mmi_frm_int_event_type interrupt_event)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
    MMI_TRACE(MMI_FW_TRC_G1_FRM, TRC_MMI_FRM_EVENT_BLOCK_GEN_INT_HDLR, interrupt_event);
    mmi_frm_block_interrupt_event_int(
        interrupt_event,    
        mmi_frm_pre_block_interrupt_event_handler,
        mmi_frm_post_block_interrupt_event_handler,
        MMI_FRM_INT_EVENT_GENERAL);
#endif
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_clear_interrupt_event_handler
 * DESCRIPTION
 *  This function could clear the designated interrupt event handler.
 * PARAMETERS
 *  interrupt_event       [IN]       framework interrupt event macro
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_clear_interrupt_event_handler(mmi_frm_int_event_type interrupt_event)
{
#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    U8 count;
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    if ((interrupt_event & MMI_FRM_INT_NON_MMI_TASK_EVENTS) && mmi_frm_process_non_mmi_task)
    {
        mmi_frm_process_non_mmi_task_interrupt(interrupt_event, MMI_FALSE);
    }

    for (count = MMI_FRM_INT_EVENT_SPECIFIC; count < MMI_FRM_INT_EVENT_TYPE_NUM; count++)
    {
        if (interrupt_event & mmi_frm_int_mask_hdlr[count].event_mask)
        {
            mmi_frm_int_mask_hdlr[count].event_mask &= ~interrupt_event;
        }
    }
#endif
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_clear_all_interrupt_event_handler
 * DESCRIPTION
 *  This function could clear all the interrupt event handler.
 * PARAMETERS
 *  interrupt_event       [IN]       framework interrupt event macro
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_clear_all_interrupt_event_handler(void)
{
#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/

    memset(mmi_frm_int_mask_hdlr, 0, sizeof(mmi_frm_int_mask_hdlr));
#endif
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_keep_block_interrupt_event
 * DESCRIPTION
 *  Phone lock feature need to block interrupt event during its process even screen
 *  has been switched.
 * PARAMETERS
 *  void
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_keep_block_interrupt_event(MMI_BOOL flag)
{
#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
    g_int_evt_control_by_app = flag;
#endif
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_reset_interrupt_event_context
 * DESCRIPTION
 *  This function could reset interrupt event context and clear all interrupt
 *  event handler.
 * PARAMETERS
 *  void
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_reset_interrupt_event_context(void)
{
#ifdef __MMI_FRM_BLOCK_INTERRUPT_MECHANISM__
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    if (g_int_evt_control_by_app)
    {
        return ;
    }
    /* 
     * Non-MMI task interruption is not through the protocol event process, so it needs to set flag to 
     * stop popup screen after EntryNewScreen and reset it when exit the screen
     */    
    if (mmi_frm_process_non_mmi_task)
    {
    #ifdef OBIGO_Q03C
        if (mmi_frm_query_interrupt_event_information(MMI_FRM_INT_WAP_MMS, NULL, NULL))
        {
            wap_suppress_popup(KAL_FALSE);
        }
    #endif /* OBIGO_Q03C */
    #if defined(__MMI_BT_MTK_SUPPORT__)
        if (mmi_frm_query_interrupt_event_information(MMI_FRM_INT_BT_TASK, NULL, NULL))
        {
            mmi_bt_suppress_popup(MMI_FALSE, (U32)NULL);
        }
    #endif /* defined(__MMI_BT_MTK_SUPPORT__) */
        mmi_frm_process_non_mmi_task = MMI_FALSE;
    }

    mmi_frm_clear_all_interrupt_event_handler();
#endif
}


#ifdef __MMI_FRAMEWORK_BACKWARD_COMPATIBLE__
/*****************************************************************************
 * FUNCTION
 *  mmi_frm_is_interrupt_group_table
 * DESCRIPTION
 *  search interrupt group event id is in interrupt
 *  group table and get the index
 * PARAMETERS
 *  eventID     [IN]     Unique Protocol/System EventID.   
 *  index       [OUT]    The index in the interrupt group table. If not find the
 *                       index is -1.
 * RETURNS
 *  MMI_BOOL
 *****************************************************************************/
static MMI_BOOL mmi_frm_is_interrupt_group_table(U16 event_id, int *index)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    int i;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    for (i = 0; i < sizeof(interruptGroupEventTable) / sizeof(InterruptGroupInfo); i++)
    {
        if (interruptGroupEventTable[i].groupID == event_id)
        {
            *index = i;
            return MMI_TRUE;
        }
    }

    *index = -1;
    return MMI_FALSE;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_query_interrupt_handler
 * DESCRIPTION
 *  query interrupt event handler
 * PARAMETERS
 *  eventID         [IN]   Unique Protocol/System EventID.      
 *  funcPtr         [OUT]  Function to be executed when receiving the interrupt event.     
 *  postfuncPtr     [OUT]  Function to be executed after receiving the interrupt event       
 * RETURNS
 *  MMI_BOOL
 *****************************************************************************/
static MMI_BOOL mmi_frm_query_interrupt_handler(U16 event_id, PsIntFuncPtr *func_ptr, PsIntFuncPtr *post_func_ptr)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    int i, j, index;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    for (i = 0; i < MAX_INTERRUPT_EVENT; i++)
    {
        if (!IS_INTERRUPT_EVENT_GROUP(interruptEventHandler[i].eventID))
        {
            /* General interrupt event */
            if (interruptEventHandler[i].eventID == event_id)
            {
                goto is_found;
            }
        }
        else
        {
            if (mmi_frm_is_interrupt_group_table(interruptEventHandler[i].eventID, &index))
            {
                /* Interrupt group event */
                j = 0;
                while (interruptGroupEventTable[index].eventID[j] != 0)
                {
                    if (interruptGroupEventTable[index].eventID[j] == event_id)
                    {
                        goto is_found;
                    }
                    j++;

                    MMI_ASSERT(j < INTERRUPT_EVENT_GREOUP_SIZE);
                }
            }
        }

    }
    return MMI_FALSE;

  is_found:
    *func_ptr = (PsIntFuncPtr) interruptEventHandler[i].entryIntFuncPtr;
    *post_func_ptr = (PsIntFuncPtr) interruptEventHandler[i].postIntFuncPtr;
    return MMI_TRUE;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_set_interrupt_event_handler
 * DESCRIPTION
 *  This function is used for register the interrupt event handler. Whenever 
 *  an event is received from the protocol corresponding function is executed.
 *  If the interrupt event handlers are registered, MMI framework  executes 
 *  the functions as follow order: Inpterrupt Event Handler, Protocol Event 
 *  Handler, Post Interrupt Event Handler.
 * PARAMETERS
 *  funcPtr         [IN] Function to be executed when receiving the interrupt event.       
 *  postfuncPtr     [IN] Function to be executed after receiving the interrupt event.       
 *  eventID         [IN] Unique Protocol/System EventID.       
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_set_interrupt_event_handler(PsIntFuncPtr func_ptr, PsIntFuncPtr post_func_ptr, U16 event_id)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    S16 count = 0;
    pBOOL isNewEvent = TRUE;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    MMI_TRACE(MMI_FW_TRC_G1_FRM, TRC_MMI_FRM_EVENT_SETINTP_HDLR, event_id);

    if (!IS_INTERRUPT_EVENT_GROUP(event_id))
    {
        /* General interrupt event will allocate from the begin */
        for (count = 0; count < maxInterruptEvent; count++)
        {
            if (interruptEventHandler[count].eventID == event_id)
            {
                isNewEvent = FALSE;
                break;
            }
            if (interruptEventHandler[count].eventID == 0)
            {
                break;
            }
        }
    }
    else
    {
        /* Interrupt group event will allocate from the end */
        for (count = MAX_INTERRUPT_EVENT - 1; count >= 0; count--)
        {
            if (interruptEventHandler[count].eventID == event_id)
            {
                isNewEvent = FALSE;
                break;
            }
            if (interruptEventHandler[count].eventID == 0)
            {
                break;
            }
        }
    }

    if (isNewEvent)
    {
        maxInterruptEvent++;
        MMI_ASSERT(maxInterruptEvent < MAX_INTERRUPT_EVENT);
    }

    interruptEventHandler[count].eventID = event_id;
    interruptEventHandler[count].entryIntFuncPtr = func_ptr;
    interruptEventHandler[count].postIntFuncPtr = post_func_ptr;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_set_group_interrupt_event_handler
 * DESCRIPTION
 *  This function is used for register the group interrupt event handlers. 
 *  If the interrupt event handlers are registered, MMI framework  executes 
 *  the functions as follow order: InpterruptFuncPtr, ProtocolFuncPtr, 
 *  InterruptPostfuncPtr.
 * PARAMETERS
 *  funcPtr         [IN] Function to be executed when receiving the interrupt event.       
 *  postfuncPtr     [IN] Function to be executed after receiving the interrupt event.       
 *  eventsID        [IN] Unique Protocol/System EventID array.       
 *  len             [IN] The EventsID array size.       
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_set_group_interrupt_event_handler(PsIntFuncPtr func_ptr, PsIntFuncPtr post_func_ptr, PU16 events_id, U8 len)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    U8 count;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    for (count = 0; count < len; count++)
    {
        MMI_TRACE(MMI_FW_TRC_G1_FRM, TRC_MMI_FRM_EVENT_SETGRPINTP_HDLR, events_id[count]);
        mmi_frm_set_interrupt_event_handler(func_ptr, post_func_ptr, events_id[count]);
    }
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_clear_interrupt_event_handler_old
 * DESCRIPTION
 *  This is used to clear interrupt event handler
 * PARAMETERS
 *  eventID     [IN] Clear the handler of event ID.       
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_clear_interrupt_event_handler_old(U16 event_id)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    MMI_TRACE(MMI_FW_TRC_G1_FRM, TRC_MMI_FRM_EVENT_CLRINTP_HDLR, event_id);
    mmi_frm_set_interrupt_event_handler(NULL, NULL, event_id);
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_clear_all_interrupt_event_handler_old
 * DESCRIPTION
 *  This is used to clear all the interrupt event handlers
 * PARAMETERS
 *  void
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_clear_all_interrupt_event_handler_old(void)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    MMI_TRACE(MMI_FW_TRC_G1_FRM, TRC_MMI_FRM_EVENT_CLRALLINTP_HDLR);

    memset(interruptEventHandler, 0, sizeof(PsInteventInfo)*maxInterruptEvent);

    maxInterruptEvent = 0;
}
#endif /*__MMI_FRAMEWORK_BACKWARD_COMPATIBLE__*/

void mmi_frm_init_event(mmi_event_struct *evt, MMI_ID evt_id, U16 size)
{
    memset(evt, 0, size);
    evt->evt_id = evt_id;
    evt->size = size;
}


void mmi_frm_init_group_event(mmi_group_event_struct *evt, MMI_ID evt_id, MMI_ID sender_id, U16 size)
{
    memset(evt, 0, size);
    evt->evt_id = evt_id;
    evt->sender_id = sender_id;
    evt->size = size;    
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_send_event
 * DESCRIPTION
 *  Send directly event to designated proc with user data.
 * PARAMETERS
 *  evt              [IN]
 *  proc             [IN]
 *  user_data        [IN]
 * RETURN VALUES
 *  MMI_RET_OK: Emit the event to the specific proc function without return value from the receiver.
 *  Others: Emit the event to the specific proc function and carry the return value from the receiver.
 *****************************************************************************/
mmi_ret mmi_frm_send_event(mmi_event_struct *evt, mmi_proc_func proc, void *user_data)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    evt->user_data = user_data;

    return proc(evt);
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_post_event
 * DESCRIPTION
 *  Send post event to designated proc with user data, it will be invoked after current
 *  function flow and before next input event like key, pen, timer, primitive.
 * PARAMETERS
 *  evt              [IN]   event structure pointer;
 *  proc             [IN]   process handler
 *  user_data        [IN]   user data pointer
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_post_event(mmi_event_struct *evt, mmi_proc_func proc, void *user_data)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    mmi_post_event_proc_struct *post_evt_p;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    MMI_ASSERT(evt != NULL && proc != NULL);
    MMI_TRACE(MMI_FW_TRC_G1_FRM, TRC_MMI_FRM_CB_POST_EVT, evt, evt->evt_id, proc, user_data);
    /* Copy event struct and push into post evt queue */
    post_evt_p = mmi_frm_malloc(sizeof(mmi_post_event_proc_struct));
    post_evt_p->evt_p = mmi_frm_malloc(evt->size);
    memcpy(post_evt_p->evt_p, evt, evt->size);
    post_evt_p->proc = proc;
    post_evt_p->evt_p->user_data = user_data;

    enqueue_post_evt((void *)post_evt_p, POST_EVT);
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_post_event_ex
 * DESCRIPTION
 *  Send post event to designated proc with user data, it will be invoked after current
 *  function flow and before next input event like key, pen, timer, primitive.
 *  And result callback will be invoked with EVT_ID_POST_CB_RST and result_cb_user_data to
 *  notify sender the result.
 * PARAMETERS
 *  evt                 [IN]   event structure pointer;
 *  proc                [IN]   designated process handler;
 *  user_data           [IN]   designated user data pointer;
 *  result_cb           [IN]   result process handler;
 *  result_cb_user_data [IN]   result user data;
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_post_event_ex(mmi_event_struct *evt, mmi_proc_func proc, void *user_data, mmi_post_event_result_proc_func result_cb, void *result_cb_user_data)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    mmi_post_event_proc_ex_struct *post_evt_ex_p;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    MMI_ASSERT(evt != NULL && proc != NULL);
    MMI_TRACE(MMI_FW_TRC_G1_FRM, TRC_MMI_FRM_CB_POST_EVT_EX, evt, evt->evt_id, proc, user_data, result_cb, result_cb_user_data);
    /* Copy event struct and push into post evt queue */
    post_evt_ex_p = mmi_frm_malloc(sizeof(mmi_post_event_proc_ex_struct));
    post_evt_ex_p->evt_p = mmi_frm_malloc(evt->size);
    memcpy(post_evt_ex_p->evt_p, evt, evt->size);
    post_evt_ex_p->proc = proc;
    post_evt_ex_p->evt_p->user_data = user_data;
    post_evt_ex_p->result_cb = result_cb;
    post_evt_ex_p->result_cb_user_data = result_cb_user_data;

    enqueue_post_evt((void *)post_evt_ex_p, POST_EVT_EX);
}


/**************************************************************************************
 * Post event mechanism
 **************************************************************************************/
/*****************************************************************************
 * FUNCTION
 *  mmi_frm_is_event_posted
 * DESCRIPTION
 *  Check if event is in post event queue.
 * PARAMETERS
 *  evt_p :      [IN]  event structure pointer.
 * RETURNS
 *  Return MMI_TRUE if the designated post event is in queue by checking event id & user data pointer,
 *  otherwise return MMI_FALSE.
 *****************************************************************************/
MMI_BOOL mmi_frm_is_event_posted(mmi_event_struct *check_evt_p)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    mmi_post_evt_node_struct *position;
    mmi_event_struct *post_evt_p;
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    if (!post_evt_header || !check_evt_p)
    {
        return MMI_FALSE;
    }
    
    for (position = post_evt_header->next; position != NULL; position = position->next)
    {/* position should point to current cell */
        post_evt_p = (mmi_event_struct *)position->evt_p;
        if (post_evt_p->evt_id == check_evt_p->evt_id && post_evt_p->user_data == check_evt_p->user_data)
        {
            return MMI_TRUE;
        }        
    }

    return MMI_FALSE;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_get_post_evt_num
 * DESCRIPTION
 *  Get event number of post queue.
 * PARAMETERS
 *  void
 * RETURNS
 *  Return event number.
 *****************************************************************************/
U32 mmi_frm_get_post_evt_num(void)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    mmi_post_evt_node_struct *position;
    U32 num = 0;
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    if (!post_evt_header)
    {
        return 0;
    }
    for (position = post_evt_header->next; position != NULL; position = position->next)
    {
        num++;
    }
    return num;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_is_post_evt_queue_empty
 * DESCRIPTION
 *  Check if post event queue is empty.
 * PARAMETERS
 *  void
 * RETURNS
 *  Return MMI_TRUE if there is some post event in queue, 
 *  otherwise return MMI_FALSE.
 *****************************************************************************/
MMI_BOOL mmi_frm_is_post_evt_queue_empty(void)
{
    return (post_evt_header == NULL) ? MMI_TRUE : MMI_FALSE;
}


/*****************************************************************************
 * FUNCTION
 *  enqueue_post_evt
 * DESCRIPTION
 *  Enqueue event into post event queue.
 * PARAMETERS
 *  evt_p             [IN]  event structure pointer;
 *  evt_flag          [IN]  post event type;
 * RETURNS
 *  Return event number.
 *****************************************************************************/
void enqueue_post_evt(void *evt_p, U8 evt_flag)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    mmi_post_evt_node_struct *position, *tmp_cell;
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    MMI_ASSERT(NULL != evt_p);
    if (!post_evt_header)
    {
        post_evt_header = mmi_frm_malloc(sizeof(mmi_post_evt_node_struct));
        memset(post_evt_header, 0, sizeof(mmi_post_evt_node_struct));
    }
    for (position = post_evt_header; position->next != NULL; position = position->next)
    /* position should point to previous cell */
        ;
    tmp_cell = mmi_frm_malloc(sizeof(mmi_post_evt_node_struct));
    tmp_cell->flag = evt_flag;
    tmp_cell->evt_p = evt_p;
    tmp_cell->next = position->next;    /* NULL */
    position->next = tmp_cell;
    post_evt_num++;
    if (post_evt_peak_num < post_evt_num)
    {
        post_evt_peak_num = post_evt_num;
    }
    MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, TRC_MMI_FRM_CB_ENQ_POST_EVT, evt_p, evt_flag, post_evt_num);
}


/*****************************************************************************
 * FUNCTION
 *  dequeue_post_evt
 * DESCRIPTION
 *  Dequeue post event with designated event type.
 * PARAMETERS
 *  evt_flag             [IN]  post event type;
 * RETURNS
 *  void
 *****************************************************************************/
void *dequeue_post_evt(U8 *evt_flag)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    mmi_post_evt_node_struct *position;
    void *evt_p;

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    if (!post_evt_header)
    {
        MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, TRC_MMI_FRM_CB_DEQ_POST_EVT_NULL);
        return NULL;
}
    position = post_evt_header->next;
    if (!position)
    {
        MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, TRC_MMI_FRM_CB_DEQ_POST_EVT_EMPTY);
        return NULL;
    }
    post_evt_header->next = position->next;
    evt_p = position->evt_p;
    *evt_flag = position->flag;
    mmi_frm_free(position);
    MMI_ASSERT(NULL != evt_p);

    if (!post_evt_header->next)
    {
        mmi_frm_free(post_evt_header);
		post_evt_header = NULL;
    }
    post_evt_num--;
    MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, TRC_MMI_FRM_CB_DEQ_POST_EVT, evt_p, ((mmi_event_struct *)evt_p)->evt_id, *evt_flag, post_evt_num);

    return evt_p;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_invoke_post_event
 * DESCRIPTION
 *  Emit post events, the callback of this events will be invoked after current 
 *  function flow.
 * PARAMETERS
 *  void
 * RETURNS
 *  Return MMI_RET_ERR_NO_POST_EVENT if there is no post event,
 *  Return MMI_RET_ERR_UNKNOWN_EVT_FLAG if can't find event flag,
 *  otherwise return result of callback function;
 *****************************************************************************/
S32 mmi_frm_invoke_post_event(void)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    void *evt_p;
    U8 evt_flag;
    S32 result = MMI_RET_ERR;
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/

#ifdef __VENUS_UI_ENGINE__
    vfx_mmi_check_update();
#endif

    if (post_evt_num == 0)
    {
        //MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, TRC_MMI_FRM_CB_INVOKE_POST_EVT_NULL);
        result = MMI_RET_ERR_NO_POST_EVENT;
    }
    else
    {
        MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, TRC_MMI_FRM_CB_INVOKE_POST_EVT_BEGIN, post_evt_num);
    }

    
    do
    {
        while (NULL != (evt_p = dequeue_post_evt(&evt_flag)))
        {
            MMI_ASSERT(NULL != evt_p);

            if (evt_flag == POST_CB_EVT)
            {
            result = MMI_FRM_CB_EMIT_EVENT(evt_p);
                mmi_frm_free(evt_p);
            }
            else if (evt_flag == POST_CB_EVT_EX)
            {
                mmi_post_evt_ex_struct *evt_ex_p = (mmi_post_evt_ex_struct *)evt_p;
                mmi_post_result_event_struct rst_evt;
                S32 rst;

                /* Send posted event */
            rst = MMI_FRM_CB_EMIT_EVENT(evt_ex_p->evt_p);

                /* Feedback to caller by result callback */
                rst_evt.evt_id = EVT_ID_POST_CB_RST;
                rst_evt.user_data = evt_ex_p->result_cb_user_data;
                rst_evt.result = rst;
                rst_evt.evt_p = evt_ex_p->evt_p;
                result = evt_ex_p->result_cb(&rst_evt);
            
                mmi_frm_free(evt_ex_p->evt_p);
                mmi_frm_free(evt_ex_p);
            }
            else if (evt_flag == POST_EVT)
            {
                mmi_post_event_proc_struct *post_evt_p = (mmi_post_event_proc_struct *)evt_p;

                result = post_evt_p->proc(post_evt_p->evt_p);
            
                mmi_frm_free(post_evt_p->evt_p);
                mmi_frm_free(post_evt_p);
            }
            else if (evt_flag == POST_EVT_EX)
            {
                mmi_post_event_proc_ex_struct *post_evt_ex_p = (mmi_post_event_proc_ex_struct *)evt_p;
                mmi_post_result_event_struct rst_evt;
                S32 rst;

                /* Send posted event to designated proc */
                rst = post_evt_ex_p->proc(post_evt_ex_p->evt_p);
            
                /* Feedback to caller by result callback */
                rst_evt.evt_id = EVT_ID_POST_CB_RST;
                rst_evt.user_data = post_evt_ex_p->result_cb_user_data;
                rst_evt.result = rst;
                rst_evt.evt_p = post_evt_ex_p->evt_p;
                result = post_evt_ex_p->result_cb(&rst_evt);

                mmi_frm_free(post_evt_ex_p->evt_p);
                mmi_frm_free(post_evt_ex_p);
            }
            else
            {
                MMI_ASSERT(0);
                result = MMI_RET_ERR_UNKNOWN_EVT_FLAG;
            }

        #ifdef __VENUS_UI_ENGINE__
            vfx_mmi_check_update();
        #endif
        }
    #ifdef __VENUS_UI_ENGINE__
        vfx_mmi_update_scene();
    #endif
    }while (post_evt_num);
    
    MMI_ASSERT(post_evt_num == 0);
    MMI_TRACE(MMI_FW_TRC_G6_FRM_DETAIL, TRC_MMI_FRM_CB_INVOKE_POST_EVT_END);

    /* After handling the post events, we check if need to dump the screen history. */
    mmi_frm_exec_post_event_end();
    mmi_frm_fix_mem_check_intigrity();
#ifdef __MMI_MEMORY_MONITOR__
    mmi_mem_mon_print_info();
#endif
    return result;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_get_evt_id
 * DESCRIPTION
 *  Get event id from event structure.
 * PARAMETERS
 *  evt :      [IN]  post event structure pointer.
 * RETURNS
 *  Return event id;
 *****************************************************************************/
U16 mmi_frm_get_evt_id(mmi_event_struct *evt)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    return evt->evt_id;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_get_evt_user_data
 * DESCRIPTION
 *  Get user data from event structure.
 * PARAMETERS
 *  evt :      [IN]  post event structure pointer.
 * RETURNS
 *  Return user data;
 *****************************************************************************/
void *mmi_frm_get_evt_user_data(mmi_event_struct *evt)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/
    
    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    return evt->user_data;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_get_post_event_number
 * DESCRIPTION
 *  Get user data from event structure.
 * PARAMETERS
 *  void
 * RETURNS
 *  Return post event number;
 *****************************************************************************/
U8 mmi_frm_get_post_event_number(void)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/

    return post_evt_num;
}

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_get_post_event_peak_num
 * DESCRIPTION
 *  This function is used to get post event peak number
 * PARAMETERS
 *  void
 * RETURNS
 *  Return post event peak number;
 *****************************************************************************/
U8 mmi_frm_get_post_event_peak_num(void)
{
    /*----------------------------------------------------------------*/
    /* Local Variables                                                */
    /*----------------------------------------------------------------*/

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    return post_evt_peak_num;
} 

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_exec_msg_end
 * DESCRIPTION
 *  execute message end process
 *  
 *  
 * PARAMETERS
 *  void
 * RETURNS
 *  void
 *****************************************************************************/
static void mmi_frm_exec_post_event_end(void)
{
     if (mmi_frm_event_get_dump_history_flag())
    {
        HistoryDump();
        mmi_frm_event_set_dump_history_flag(MMI_FALSE);

        /* if need to dump the screen id. */
        mmi_frm_dump_screen_id();
    }
    mmi_frm_close_active_empty_group();

#ifdef __MMI_LCM_PRIMITIVE_FLUSH__
     mmi_frm_screen_commit();
#endif
}


#ifdef __MMI_LCM_PRIMITIVE_FLUSH__
/*****************************************************************************
 Anti-blink mechanism
 *****************************************************************************/
void mmi_frm_screen_set_sse_backup(MMI_BOOL isOn)
{
    mmi_frm_scr_mgm_data.sseBackupOn = isOn;
}

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_scr_mgm_init
 * DESCRIPTION
 *  init screen mgm data structure for anti blinking and SSE
 *  called by the initialize process of mmi task
 * PARAMETERS
 *  None   
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_scr_mgm_init()
{
    U32 i;
    mmi_frm_scr_mgm_data.dirty = MMI_FALSE;
    mmi_frm_scr_mgm_data.apControlBltOnce = MMI_FALSE;
    mmi_frm_screen_set_sse_backup(MMI_TRUE);
    mmi_frm_scr_mgm_data.bltMode = MMI_FRM_SCR_BLT_DEFAULT;
    for (i = 0; i < MAX_SCREEN_LOG_SIZE; i++)
    {
        mmi_frm_scr_mgm_data.scrnLogData[i] = MMI_FRM_SCREEN_ID_IVALID;
    }
    mmi_frm_scr_mgm_data.scrnLogIdx = 0;
    mmi_frm_scr_mgm_data.changeRecording = MMI_TRUE;
    mmi_frm_scr_mgm_data.prevScrnLevel = 0;
    mmi_frm_scr_mgm_data.currScrnLevel = 0;
}

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_scr_mgm_deinit
 * DESCRIPTION
 *  init screen mgm data structure for anti blinking and SSE
 *  called by the initialize process of mmi task
 * PARAMETERS
 *  None   
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_scr_mgm_deinit()
{
    U32 i;
    mmi_frm_scr_mgm_data.dirty = MMI_FALSE;
    mmi_frm_scr_mgm_data.apControlBltOnce = MMI_FALSE;
    mmi_frm_screen_set_sse_backup(MMI_FALSE);
    mmi_frm_scr_mgm_data.bltMode = MMI_FRM_SCR_BLT_DEFAULT;
    for (i = 0; i < MAX_SCREEN_LOG_SIZE; i++)
    {
        mmi_frm_scr_mgm_data.scrnLogData[i] = MMI_FRM_SCREEN_ID_IVALID;
    }
    mmi_frm_scr_mgm_data.scrnLogIdx = 0;
    mmi_frm_scr_mgm_data.changeRecording = MMI_FALSE;
    mmi_frm_scr_mgm_data.prevScrnLevel = 0;
    mmi_frm_scr_mgm_data.currScrnLevel = 0;
}

/*****************************************************************************
 * FUNCTION
 *  lock_screen
 * DESCRIPTION
 *  internal use function for lock lcd blit
 *  
 * PARAMETERS
 *  None   
 * RETURNS
 *  void
 *****************************************************************************/
static void lock_screen(void)
{
    if (g_mmi_frm_screen_enable_anti_blink)
    {
        gdi_lcd_set_high_priority_freeze(MMI_TRUE);
    }
}

/*****************************************************************************
 * FUNCTION
 *  unlock_screen
 * DESCRIPTION
 *  internal function for unlock lcd blit
 *  
 * PARAMETERS
 *  None   
 * RETURNS
 *  void
 *****************************************************************************/
static void unlock_screen(void)
{
    gdi_lcd_set_high_priority_freeze(MMI_FALSE);
}

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_refrsh_lcm
 * DESCRIPTION
 *  internal function for blit lcm
 *  
 * PARAMETERS
 *  None   
 * RETURNS
 *  void
 *****************************************************************************/
static void mmi_frm_refrsh_lcm()
{
    /* Flush content to LCM */
    gdi_lcd_set_high_priority_freeze(FALSE);
#if defined(__MMI_SCREEN_SWITCH_EFFECT__)
    if (!mmi_frm_scr_mgm_data.apControlBltOnce)
    {
        gui_sse_launch();
    }
    else
    {
        gui_screen_switch_effect_reset_flag();
        gdi_lcd_repaint_all();
    }
#else /* defined(__MMI_SCREEN_SWITCH_EFFECT__) */
    gdi_lcd_repaint_all();
#endif /* defined(__MMI_SCREEN_SWITCH_EFFECT__) */

#if defined(__MMI_VUI_ENGINE__)
    vfx_mmi_screen_entered();
#endif /* defined(__MMI_VUI_ENGINE__) */
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_set_curr_scr_blt_mode
 * DESCRIPTION
 *  Interface for application to set blit mode of current screen
 *   
 *  - screen level operation
 *  - only affect current screen
 *  - the anti-blink mechanism will be disabled at the screen
 *  - the flush mode will be reset after exit a screen
 *  
 * PARAMETERS
 *     MMI_FRM_SCR_BLT_IMMEDIATE: gdi_lcd_blt will update screen immediately
 *          
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_set_curr_scr_blt_mode(mmi_frm_scr_blt_mode_enum mode)
{
    mmi_frm_scr_mgm_data.bltMode = mode;

    switch(mode)
    {
    case MMI_FRM_SCR_BLT_PRIMITIVE:
        lock_screen();
        break;
    case MMI_FRM_SCR_BLT_IMMEDIATE:
        unlock_screen();
        /* will update screen, reset dirty flag to flase */
        mmi_frm_scr_mgm_data.dirty = MMI_FALSE;
        mmi_frm_scr_mgm_data.apControlBltOnce = MMI_TRUE;
        break;
    }    
    return;
}

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_ui_force_update_now
 * DESCRIPTION
 *  Get screen ID of the screen that is commited previously.
 *  This funciton is prepare for SSE specially, applicaion should not directly use it.
 *  
 * PARAMETERS
 *  None   
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_ui_force_update_now(void)
{
    switch (mmi_frm_scr_mgm_data.bltMode)
    {
    case MMI_FRM_SCR_BLT_PRIMITIVE:
        unlock_screen();
        gdi_lcd_repaint_all();
        /* 
            Assumption: once a screen invoke mmi_frm_ui_force_update_now()
            the screen will not be locked untill we enter next screen()
        */
        break;
    default:  
        gdi_lcd_repaint_all();
        break;
    }    
    /* have updated screen, reset dirty flag to flase */
    mmi_frm_scr_mgm_data.dirty = MMI_FALSE;
    mmi_frm_scr_mgm_data.apControlBltOnce = MMI_TRUE;
}

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_screen_get_committed_id
 * DESCRIPTION
 *  Get screen ID of the screen that is commited previously.
 *  This funciton is prepare for SSE specially, applicaion should not directly use it.
 *  
 * PARAMETERS
 *  offset  1 -> illeage use
 *  offset  0 -> latest committed 
 *          -1 -> the previously committed id of latest comitted
 *          -2 -> the previously committed id of offset (-1)
 *          ...
 * RETURNS
 *  void
 *****************************************************************************/
U16 mmi_frm_screen_get_committed_id(S32 offset)
{
    S32 targetIdx;
    MMI_ASSERT(offset <= 0);
    targetIdx = (mmi_frm_scr_mgm_data.scrnLogIdx - 1 + offset) % MAX_SCREEN_LOG_SIZE;
    return mmi_frm_scr_mgm_data.scrnLogData[targetIdx];
}

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_enable_anti_blink
 * DESCRIPTION
 * Switch on/off antiblink mechanism
 * PARAMETERS
 *  enable TRUE  -> enable anti blink
 *  disable TRUE  -> disableable anti blink
 * RETURNS
 *  void
 *****************************************************************************/

void mmi_frm_enable_anti_blink(MMI_BOOL enable)
{
	g_mmi_frm_screen_enable_anti_blink = enable;

}

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_screen_commit
 * DESCRIPTION
 *  
 *  Finish current message iteration. Commit all the changes of screen.
 * PARAMETERS
 *  void
 * RETURNS
 *  void
 *****************************************************************************/
static void mmi_frm_screen_commit(void)
{

    MMI_ID group_id = GRP_ID_INVALID;
    MMI_ID scrn_id  = GRP_ID_INVALID;

    mmi_frm_screen_set_sse_backup(MMI_TRUE);
   if (((mmi_frm_scr_mgm_data.dirty == MMI_FALSE) &&
        (mmi_frm_scr_mgm_data.apControlBltOnce == MMI_FALSE))
        ||(g_mmi_frm_screen_enable_anti_blink == MMI_FALSE))
    {
#if defined(__MMI_SCREEN_SWITCH_EFFECT__)
        gui_screen_switch_effect_reset_flag();
#endif
        return;
    }

    /*----------------------------------------------------------------*/
    /* Code Body                                                      */
    /*----------------------------------------------------------------*/
    mmi_frm_get_active_scrn_id(&group_id, &scrn_id);
    //activeScrnId = GetActiveScreenId();
    mmi_frm_scr_mgm_data.scrnLogData[mmi_frm_scr_mgm_data.scrnLogIdx] = (group_id<<16)|(scrn_id);
    mmi_frm_scr_mgm_data.prevScrnLevel = mmi_frm_scr_mgm_data.currScrnLevel;
    mmi_frm_scr_mgm_data.currScrnLevel = mmi_frm_get_screen_level(scrn_id);
    mmi_frm_scr_mgm_data.currScrnLevel -= (gui_sse_get_is_dummy_screen()) ? (1) : (0);
    mmi_frm_scr_mgm_data.scrnLogIdx = (mmi_frm_scr_mgm_data.scrnLogIdx + 1) % MAX_SCREEN_LOG_SIZE;
    
    mmi_frm_scr_mgm_data.changeRecording = MMI_TRUE;
    if ( mmi_frm_scr_mgm_data.dirty)
    {
        mmi_frm_scr_mgm_data.dirty = MMI_FALSE;
        mmi_frm_refrsh_lcm();
    }
    mmi_frm_scr_mgm_data.apControlBltOnce = MMI_FALSE;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_screen_is_sse_backup_on
 * DESCRIPTION
 *  
 *  The function is designed for SSE to determine the timing of the screen 
 *  that is going to change.
 * PARAMETERS
 *  void
 * RETURNS
 *  void
 *****************************************************************************/
MMI_BOOL mmi_frm_screen_is_sse_backup_on(void)
{
    return mmi_frm_scr_mgm_data.sseBackupOn;
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_screen_set_change_record_mode
 * DESCRIPTION
 *  
 *  Turn on/off change recording mode. This function is used for dealing with some
 *  special case that screens are not real screens and should be skipped recording the
 *  screen change. For example, group adaptor. 
 * PARAMETERS
 *  void
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_screen_set_change_record_mode(MMI_BOOL changeRecording)
{
    mmi_frm_scr_mgm_data.changeRecording = changeRecording;
}



/*****************************************************************************
 * FUNCTION
 *  mmi_frm_screen_change
 * DESCRIPTION
 *  
 *  The function will be invoked after scrn_active and mmi_frm_entry_new_screen_int
 *  This is not standard interface to applicaiton, application should not use it!
 * PARAMETERS
 *  void
 * RETURNS
 *  void
 *****************************************************************************/
void mmi_frm_screen_change(void)
{
    
    /* skip some special case such as group adaptor */
    if (mmi_frm_scr_mgm_data.changeRecording == MMI_FALSE)
    {
        return;
    }
    
    if (mmi_frm_scr_mgm_data.dirty == MMI_FALSE)
    {
        mmi_frm_scr_mgm_data.dirty = MMI_TRUE;
    }
    // Reset blit mode to default mode
    mmi_frm_set_curr_scr_blt_mode(MMI_FRM_SCR_BLT_DEFAULT);
}


/*****************************************************************************
 * FUNCTION
 *  mmi_frm_screen_get_direction
 * DESCRIPTION
 *  
 *  The function is interface for SSE to get screen moving direction (forward or backward)
 *  SSE can refer this value as a criteria to determine the effect that shoule be applied.
 * PARAMETERS
 *  None
 * RETURNS
 *  > 0     forward
 *  = 0     same level
 *  < 0     backward
 *****************************************************************************/
S32 mmi_frm_screen_get_direction()
{
    return  mmi_frm_scr_mgm_data.currScrnLevel  - mmi_frm_scr_mgm_data.prevScrnLevel;
}

/*****************************************************************************
 * FUNCTION
 *  mmi_frm_screen_get_depth
 * DESCRIPTION
 *  
 *  The function is interface for SSE to get current screen depth.
 *  SSE can refer this value as a criteria to determine the effect that shoule be applied.
 * PARAMETERS
 *  None
 * RETURNS
 *  Current screen level
 *****************************************************************************/
U32 mmi_frm_screen_get_depth()
{
    return  mmi_frm_scr_mgm_data.currScrnLevel;
}


#else /* __MMI_LCM_PRIMITIVE_FLUSH__ */
//Dummy function for turn off the primitive flush feature
void mmi_frm_scr_mgm_init(){}
void mmi_frm_set_curr_scr_blt_mode(mmi_frm_scr_blt_mode_enum mode){}
void mmi_frm_ui_force_update_now(void){}
void mmi_frm_screen_change(void){}

#endif /* __MMI_LCM_PRIMITIVE_FLUSH__ */


//#define __MMI_LCM_PRIMITIVE_FLUSH_UNIT_TEST__


#ifdef __MMI_LCM_PRIMITIVE_FLUSH_UNIT_TEST__
/*****************************************************************************
 Anti blinking mechanism test case  
 *****************************************************************************/


extern void goto_main_meu(void);
extern void mmi_phb_entry_main_menu(void);
extern void EntryOrganizer(void);
extern void ClndrPreEntryApp(void);

static void antiblink_test_hist_entry1(void)                                                              
{                                                                                                     
    EntryNewScreen(30000, NULL, antiblink_test_hist_entry1, NULL);
    mmi_frm_set_curr_scr_blt_mode(MMI_FRM_SCR_BLT_IMMEDIATE);
    ShowCategory65Screen((U8*) L"Immediate mode, should appear", IMG_GLOBAL_INFO, NULL);
}

static void antiblink_test_hist_entry2(void)                                                              
{                                                                                                     
    EntryNewScreen(30000, NULL, antiblink_test_hist_entry2, NULL);
    ShowCategory65Screen((U8*) L"default mode, should disappear", IMG_GLOBAL_INFO, NULL);
}


void start_anitblink_group_test(void)
{
    goto_main_menu();
    mmi_phb_entry_main_menu();
    GoBackHistory();
    GoBackHistory();
    goto_main_menu();
    EntryOrganizer();
    ClndrPreEntryApp();
    antiblink_test_hist_entry1();
    antiblink_test_hist_entry2();
    GoBackHistory();
    GoBackHistory();
    GoBackHistory();
    GoBackHistory();
    GoBackHistory();
}

void start_anitblink_group_test2(void)
{
    mmi_phb_entry_main_menu();
    EntryOrganizer();
    GoBackHistory();
    GoBackHistory();
    GoBackHistory();
}
#endif /*__MMI_LCM_PRIMITIVE_FLUSH_UNIT_TEST__*/



